package com.datas.service.baseentity;

import com.datas.beans.DatatablesPagerWithRootFilter;
import com.datas.beans.DeptListTreeParam;
import com.datas.db.hibernatebeans.UmsDepartment;
import com.datas.service.GuanlianService;
import com.datas.utils.hbn.HbnTxRuner;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created by jige0727 on 2017/5/28.
 * 部门
 */
@Service
public class DepartmentsService {
    @Autowired
    GuanlianService guanlianService;

    public Integer create(UmsDepartment dept) {
        Integer res = (Integer) new HbnTxRuner() {
            @Override
            protected Object dataLogic() throws Exception {
                return create(dept, getCurrentSession());
            }
        }.runTx();
        return res;
    }

    public Integer create(UmsDepartment dept, Session session) throws Exception {
        if (!isExistPageRes(dept, session)) {
            session.save(dept);
            setParentInfo(dept, session);
            session.update(dept);
            return 1;
        }
        return 0;
    }

    private Boolean isExistPageRes(UmsDepartment dept, Session session) throws Exception {
        String hql = "select count(*) from UmsDepartment i where i.parent_dept_id=:pid and i.dept_name=:dept_name ";
        Long count = (Long) session.createQuery(hql)
                .setParameter("pid", dept.getParent_dept_id())
                .setParameter("dept_name", dept.getDept_name())
                .uniqueResult();
        return count != null && count > 0;
    }

    private void setParentInfo(UmsDepartment dept, Session session) throws Exception {
        if (dept.getParent_dept_id() != null) {
            if (dept.getId().equals(dept.getParent_dept_id())) {
                throw new Exception("wrong parent -1");
            }
            UmsDepartment parentData = session.get(UmsDepartment.class, dept.getParent_dept_id());
            if (parentData == null) {
                throw new Exception("wrong parent -2");
            }
            //设置父级名称
            dept.setParent_dept_name(parentData.getDept_name());
            //设置自己的结构
            dept.setStruct(parentData.getStruct() + "-" + dept.getId());
        } else {
            dept.setStruct("" + dept.getId());
        }
    }

    public Integer modify(UmsDepartment dept) {
        Integer res = (Integer) new HbnTxRuner() {
            @Override
            protected Object dataLogic() throws Exception {
                return modify(dept, getCurrentSession());
            }
        }.runTx();
        return res;
    }

    private Integer modify(UmsDepartment dept, Session session) throws Exception {
        UmsDepartment dataInDb = session.get(UmsDepartment.class, dept.getId());
        dept.setCreate_date(dataInDb.getCreate_date());
        dept.setModify_date(new Date());
        dept.setParent_dept_id(dataInDb.getParent_dept_id());
        dept.setParent_dept_name(dataInDb.getParent_dept_name());
        dept.setStruct(dataInDb.getStruct());
        session.evict(dataInDb);

        session.update(dept);
        setParentInfo(dept, session);
        session.update(dept);
        return 1;
    }

    /**
     * 返回 1成功 0失败，有子节点
     *
     * @param id
     * @return
     */
    public Integer delete(Integer id) {
        Integer res = (Integer) new HbnTxRuner() {
            @Override
            protected Object dataLogic() throws Exception {
                UmsDepartment data = getCurrentSession().get(UmsDepartment.class, id);
                if (!isHasChildNode(data, getCurrentSession())) {
                    guanlianService.delGl_all_dept(id, getCurrentSession());
                    getCurrentSession().delete(data);
                    return 1;
                }
                return 0;
            }
        }.runTx();
        return res;
    }

    private Boolean isHasChildNode(UmsDepartment dept, Session session) {
        String struct = dept.getStruct() + "-%";
        String hql = "select count(*) from UmsDepartment i where i.struct like :struct";
        Long count = (Long) session.createQuery(hql).setParameter("struct", struct).uniqueResult();
        return count > 0;
    }

    public UmsDepartment info(Integer id) {
        UmsDepartment data = (UmsDepartment) new HbnTxRuner() {
            @Override
            protected Object dataLogic() throws Exception {
                return getCurrentSession().get(UmsDepartment.class, id);
            }
        }.run();
        return data;
    }

    /////////////////////////////////////////
    public void list(DatatablesPagerWithRootFilter pager) {
        Integer res = (Integer) new HbnTxRuner() {
            @Override
            protected Object dataLogic() throws Exception {
                List<UmsDepartment> data = list(pager, getCurrentSession());
                pager.setData(data);
                pager.setRecordsFiltered(list_filtered(pager, getCurrentSession()));
                pager.setRecordsTotal(list_total(getCurrentSession()));
                return 1;
            }
        }.run();
    }

    private List<UmsDepartment> list(DatatablesPagerWithRootFilter pager, Session session) {
        String searchValue = pager.getSearchValue();
        String hql = "from UmsDepartment i " +
                "where i.disabled =0 " +
                "and (i.dept_name like :searchValue " +
                "or i.dept_code like :searchValue " +
                "or i.mobilephone like :searchValue " +
                "or i.email like :searchValue " +
                "or i.tel like :searchValue) ";
        UmsDepartment root = null;
        if (pager.getFilterRootId() != null) {
            root = session.get(UmsDepartment.class, pager.getFilterRootId());
            if (root != null) {
                hql += "and (i.id=:rootId or i.struct like :struct) ";
            }
        }
        Query query = session.createQuery(hql);
        if (root != null) {
            query.setParameter("struct", root.getStruct() + "-%");
            query.setParameter("rootId", root.getId());
        }
        List<UmsDepartment> data = query
                .setParameter("searchValue", searchValue)
                .setFirstResult(pager.getStart())
                .setMaxResults(pager.getLength())
                .list();
        return data;
    }

    private Long list_filtered(DatatablesPagerWithRootFilter pager, Session session) {
        String searchValue = pager.getSearchValue();
        String hql = "select count(*) from UmsDepartment i " +
                "where i.disabled =0 " +
                "and (i.dept_name like :searchValue " +
                "or i.dept_code like :searchValue " +
                "or i.mobilephone like :searchValue " +
                "or i.email like :searchValue " +
                "or i.tel like :searchValue) ";
        UmsDepartment root = null;
        if (pager.getFilterRootId() != null) {
            root = session.get(UmsDepartment.class, pager.getFilterRootId());
            if (root != null) {
                hql += "and (i.id=:rootId or i.struct like :struct) ";
            }
        }
        Query query = session.createQuery(hql);
        if (root != null) {
            query.setParameter("struct", root.getStruct() + "-%");
            query.setParameter("rootId", root.getId());
        }
        Long count = (Long) query
                .setParameter("searchValue", searchValue)
                .uniqueResult();
        return count;
    }

    private Long list_total(Session session) {
        String hql = "select count(*) from UmsDepartment i " +
                "where i.disabled =0 ";
        Long count = (Long) session.createQuery(hql)
                .uniqueResult();
        return count;
    }

    public JSONArray listTree(DeptListTreeParam param) {
        JSONArray data = new JSONArray();
        new HbnTxRuner() {
            @Override
            protected Object dataLogic() throws Exception {
                List<UmsDepartment> datas = getCurrentSession()
                        .createQuery("from UmsDepartment i").list();
                for (UmsDepartment item : datas) {
                    int depth = item.getStruct().split("-").length;
                    if (param != null
                            && (new Integer(1)).equals(param.getFactoryOnly())
                            && depth > 2) {
                        continue;
                    }
                    JSONObject stat = new JSONObject();
                    stat.put("disabled", depth != 2);
                    data.put(new JSONObject()
                            .put("id", item.getId())
                            .put("text", item.getDept_name())
                            .put("parent", item.getParent_dept_id() == null ? "#" : item.getParent_dept_id())
                            .put("struct", item.getStruct())
                            .put("state", stat)
                    );
                }
                return 1;
            }
        }.run();
        return data;
    }

    public JSONArray listTreeWithRoleGL(Integer userid) {
        Set<Integer> ids = new HashSet<>();
        new HbnTxRuner() {
            @Override
            protected Object dataLogic() throws Exception {
                List<Integer> datas = getCurrentSession()
                        .createQuery("select i.departments_id " +
                                "from UmsUser_UmsDepartment i where i.users_id=:userid ")
                        .setParameter("userid", userid).list();
                ids.addAll(datas);
                return 1;
            }
        }.run();
        return new JSONArray(ids);
    }

    public JSONArray listTreeForMngDept(Integer userid) {
        Set<Integer> ids = new HashSet<>();
        new HbnTxRuner() {
            @Override
            protected Object dataLogic() throws Exception {
                List<Integer> datas = getCurrentSession()
                        .createQuery("select i.departments_id " +
                                "from UmsUser_UmsDepartment_mng i where i.users_id=:userid ")
                        .setParameter("userid", userid).list();
                ids.addAll(datas);
                return 1;
            }
        }.run();
        return new JSONArray(ids);
    }
}
